<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <title>Sticky-components</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        body {
            height: 1500px;
            background: #d9d9d9;
        }

        .topbar {
            width: 100%;
            background: lightblue;
            height: 80px;
            color: #fff;
            text-align: center;
            opacity: .5;
            font-size:50px;
        }
        
        .btn{
            padding:8px;
            border-radius:4px;
            border:none;
            background:goldenrod;
            outline: none;
            cursor: pointer;
            color:#fff;
            box-shadow: 0px 2px 10px 2px rgba(0,0,0,.5)
        }
        
        .test{
            width:300px;
            margin:0 auto;
            text-align: center;
        }

        p{
            margin:5px;
        }
        button {
            width: 100px;
        }

        /* .sticky只切换状态,其余宽高需要自行设置,例如导航条需要width:100%,其他元素同理 */

        .sticky {
            position: fixed;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <nav class="topbar">
        Sticky-Topbar
    </nav>
    <p>段落 1</p>
    <p>段落 2</p>
    <p>段落 3</p>
    <p>段落 4</p>
    <p>段落 5</p>
    <p>段落 6</p>
    <p>段落 7</p>
    <p>段落 8</p>
    <p>段落 9</p>
    <div class="test">
        <button class="btn">被粘住的按钮</button>
        <button class="btn">被黏住的按钮</button>
    </div>
    <p>段落 10</p>
    <script>
        class Sticky {
            constructor(el, top_val,left_val) {
                this.$el = $(el)
                this.top_Val = top_val || 0
                this.left_Val = left_val ||0
                this.cacheOffset()
                this.getWrapper()
                this.bindEvent()
            }
            cacheOffset() { //缓存元素位置信息
                this.offsets = []
                this.$el.each((index, el) => {
                    this.offsets[index] = $(el).offset()
                })
            }
            bindEvent() {//绑定滚动事件
                $(window).on('scroll', () => {
                    let scrollY = window.scrollY
                    this.$el.each((index, el) => {
                        let $el = $(el)
                        if (scrollY + this.top_Val > this.offsets[index].top) {//设置触发条件
                            $el.addClass('sticky').css({
                                top: this.top_Val,
                                left:this.left_Val,
                                transform:`translateX(-${this.left_Val})`
                            })
                        } else {
                            $el.removeClass('sticky')
                            $el.css({transform:`translateX(${0})`})
                        }
                    })
                })
            }
            getWrapper() {
                this.$el.each((index, el) => { //设置placeholder
                    let $el = $(el)
                    $el.wrap('<div class="placeHolder"></div>')
                    $el.parent('.placeHolder').height($el.outerHeight(false))
                })
            }
        }
        new Sticky('.topbar')
        new Sticky('.test',80,'50%')
    </script>
</body>

</html>